package com.httpclient.httpsDemo;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/*
https的网址：有认证证书的网站，这时候请求这样的网址有两个方法。
第一：通过密钥配置httpclient请求。
第二：配置httpclient绕过认证。
 */
public class HttpsDemo {

    /**
     * 绕过Https的认证发送请求
     */
    public static void httpsUtils(){
        //创建注册方式
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", trustCreateHttps())
                .build();

        //创建一个ConnectionManager(这里创建了一个httpclient的连接池）
        PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager(registry);

        //定制CloseableHttpClient对象：将池子创建完毕后放入到httpclient中。通过builder方法创建可关闭的httpclient对象
        HttpClientBuilder httpClientBuilder = HttpClients.custom().setConnectionManager(pool);
        CloseableHttpClient closeableHttpClient =httpClientBuilder.build();

        String url="https://www.baidu.com/";
        HttpPost httpPost=new HttpPost(url);
        CloseableHttpResponse response=null;
        try {
            response = closeableHttpClient.execute(httpPost);
            //获得响应结果
            HttpEntity entity = response.getEntity();
//            对HttpEntity操作的工具类
            String result = EntityUtils.toString(entity, "UTF-8");
            System.out.println(result);
            //确保流关闭
            EntityUtils.consume(entity);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (response!=null){
                    response.close();
                }
                if (httpPost!=null){
                    httpPost.releaseConnection();
                }
                if (closeableHttpClient!=null){
                    closeableHttpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

    /**
     * 创建支持安全协议的连接工厂
     * @return
     */
    private static ConnectionSocketFactory trustCreateHttps() {

        SSLContextBuilder sslContextBuilder=new SSLContextBuilder();
        try {
            sslContextBuilder.loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                    return true;
                }
            });
            SSLContext sslContext = sslContextBuilder.build();

            SSLConnectionSocketFactory sslConnectionSocketFactory =
                    new SSLConnectionSocketFactory(sslContext, new String[]{
                            "SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"
                    }, null, NoopHostnameVerifier.INSTANCE);

            return sslConnectionSocketFactory;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
       return null;
    }
}
